﻿using System;

namespace Module_Debug.Hardware
{
    class ICS307
    {
        public UInt32 calculate_idt307_config(float output_clk)
        {
            UInt32 idt307_config = 0x300000;
            UInt32 VDW, RDW, OD, valid_VDW = 0, valid_RDW = 0, true_OD = 0, valid_OD = 0;
            float x, y, tol = 10, tol_temp;
            for (OD = 2; OD < 11; OD++)
            {
                if (OD == 9)
                {
                    continue;
                }
                else
                {
                    x = output_clk * OD / (float)50.0;
                    if ((x > (float)1.1) && (x <= 8))
                    {
                        for (RDW = 1; RDW < 128; RDW += 1)
                        {
                            for (VDW = 4; VDW < 512; VDW += 1)
                            {
                                y = (VDW + 8) / ((float)(RDW + 2));
                                if ((y > 1.1) && (y <= 8))
                                {
                                    if (y > x)
                                    {
                                        tol_temp = y - x;
                                    }
                                    else
                                    {
                                        tol_temp = x - y;
                                    }
                                    if (tol_temp < tol)
                                    {
                                        valid_RDW = RDW;
                                        valid_VDW = VDW;
                                        valid_OD = OD;
                                        tol = tol_temp;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            switch (valid_OD)
            {
                case 2:
                    true_OD = 1;
                    break;
                case 3:
                    true_OD = 6;
                    break;
                case 4:
                    true_OD = 3;
                    break;
                case 5:
                    true_OD = 4;
                    break;
                case 6:
                    true_OD = 7;
                    break;
                case 7:
                    true_OD = 5;
                    break;
                case 8:
                    true_OD = 2;
                    break;
                case 10:
                    true_OD = 0;
                    break;
            }
            idt307_config = idt307_config | (true_OD << 16) | (valid_VDW << 7) | valid_RDW;
            return idt307_config;
        }
    }
}
